<?php
abstract class Slash_Client_ICalendarObject
{
	
	protected $lines = array();
	protected $objects = array();
	
	function __construct($lines, $objects)
	{
		foreach($lines as $line)
		{
			list($key, $value) = explode(":", $line);
			if (strpos($key, "DTSTART;") === 0)
			{
				$parts = explode(";", $key);
				$tzid = substr($parts[1], 5);
				//print "Start-line: $line; tzid=$tzid\n";
				$this->lines["DTSTART"] = array("tzid"=>$tzid, "date"=>$value);
			} else if (strpos($key, "DTEND;") === 0)
			{
				$parts = explode(";", $key);
				$tzid = substr($parts[1], 5);
				$this->lines["DTEND"] = array("tzid"=>$tzid, "date"=>$value);
			} else {
				$this->lines[$key] = $value;
			}
		}
		$this->objects = $objects;
	}
	
	public static function parseObject(&$vcal)
	{
		$obj = null;
		$lines = array();
		$objects = array();
		list($junk, $line) = each($vcal);
		//print "Read $line\n";
		if (preg_match("/BEGIN:(.*)\r$/", $line, $matches))
		{
			/*
			 * If the line is a BEGIN: line, parse an object.
			 * If it's an "END: line, check it's me that's ending, and then return me.
			 * Otherwise store a line.
			 */ 
			$objName = $matches[1];
			//print "Parsing $objName object\n";		
			while (list($junk, $line) = each($vcal))
			{
				if (preg_match("/BEGIN:(.*)\r$/", $line, $matches))
				{
					switch ($matches[1])
					{
						case "VCALENDAR":
							prev($vcal);
							$objects[] = Slash_Client_VCalendar::parseObject($vcal, $matches[1]);
							break;
						case "VEVENT":
							prev($vcal);
							$objects[] = Slash_Client_VEvent::parseObject($vcal, $matches[1]);
							break;
						case "VTIMEZONE":
							prev($vcal);
							$objects[] = Slash_Client_VTimezone::parseObject($vcal, $matches[1]);
							break;
						case "VALARM":
							prev($vcal);
							$objects[] = Slash_Client_VAlarm::parseObject($vcal, $matches[1]);
							break;
						case "STANDARD":
							prev($vcal);
							$objects[] = Slash_Client_Standard::parseObject($vcal, $matches[1]);
							break;
						case "DAYLIGHT":
							prev($vcal);
							$objects[] = Slash_Client_Daylight::parseObject($vcal, $matches[1]);
							break;
						default:
							throw new Exception("Unsupported ICalendar object type: $matches[1]");
					}
				} else if (preg_match("/END:(.*)\r$/", $line, $matches))
				{
					//print "Found an END: while parsing a $objName object\n";
					if ($matches[1] != $objName)
					{
						print "Error: found the END of a $matches[1] while parsing a $objName: $line\n";
						throw new Exception("Invalid VCALENDAR object");
					}
					switch ($objName)
					{
						case "VCALENDAR":							
							$obj = new Slash_Client_VCalendar($lines, $objects);
							break;
						case "VTODO":							
							$obj = new Slash_Client_VTodo($lines, $objects);
							break;
						case "VEVENT":							
							$obj = new Slash_Client_VEvent($lines, $objects);
							break;
						case "VTIMEZONE":							
							$obj = new Slash_Client_VTimezone($lines, $objects);
							break;
						case "VALARM":							
							$obj = new Slash_Client_VAlarm($lines, $objects);
							break;
						case "STANDARD":							
							$obj = new Slash_Client_Standard($lines, $objects);
							break;
						case "DAYLIGHT":							
							$obj = new Slash_Client_Daylight($lines, $objects);
							break;
						default:
							throw new Exception("Unsupported ICalendar object type: $objName");
					}
					break;
				} else {
					$lines[] = trim($line);
				}
			}
		}
		//print "Returning a " . get_class($obj) . "\n";
		return $obj;
	}
	
	public function toString()
	{
		//print "Converting a " . get_class($this) . " to a string\n";
		$objName = $this->OBJNAME;
		$str="BEGIN:$objName\r\n";
		foreach($this->lines as $key=>$value)
		{
			$str .= "$key:$value\r\n";
		}
		foreach ($this->objects as $object)
		{
			$str .= $object->toString();
		}
		$str .= "END:$objName\r\n";
		return $str;
	}
	
}